package com.liu.controller;

import com.liu.pojo.User;
import com.liu.util.HttpServletFactory;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @Author 老刘Matthew
 * @Timestamp 2022/7/18 15:06
 * @Description
 */
public class GenericServlet extends HttpServlet implements HttpServletFactory {

    // Server端维护Session及相关变量副本，供后台使用
    private static HttpSession session;

    private static User sessionUser;

    private HttpServletRequest request;

    private HttpServletResponse response;

    private String url;

    private Boolean isRedirect = false;

    private Boolean isAjax = false;

    private Class<? extends GenericServlet> clazz;

    protected GenericServlet() {

        logger.warn("----------> GenericServlet() : 建议使用GenericServletBuilder构造Servlet！");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response, Class<? extends GenericServlet> clazz) {

        try {

            logger.info("----------> doPost : " + request.getRequestURI());

            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");

            new GenericServletBuilder(request, response, clazz) //
                    .build()  //
                    .getRequestMapping();

        } catch (Exception e) {
            logger.error("控制转发异常！", e);
        }
    }

    protected void getRequestMapping(String... params) throws IOException {

        String url = this.getUrl();

        if (isRedirect)
            response.sendRedirect(url);
//        else if (isAjax)
//            response.getWriter().print(params[0]);
        else if (null != url && !url.isEmpty() && url.contains("_do"))
            executeRequestMappingWithProcess();
        else
            executeRequestMapping();

    }

    protected void executeRequestMapping() {

        try {

            String url = this.getUrl();

            request.getRequestDispatcher(toJsp(url)).forward(request, response);

        } catch (ServletException | IOException e) {
            logger.error("Servlet转发异常！", e);
        }
    }

    protected void executeRequestMappingWithProcess() {

        try {

            String url = this.getUrl();

            logger.info("path : " + url);

            if (!url.contains(".")) {

                Class<? extends GenericServlet> clazz = this.getClazz();
                Method method = clazz.getDeclaredMethod(url, HttpServletRequest.class, HttpServletResponse.class);

                method.invoke(clazz.newInstance(), request, response);

            } else
                logger.warn("Servlet请求url资源过滤：" + url);

        } catch (InvocationTargetException | NoSuchMethodException | IllegalAccessException | InstantiationException e) {
            logger.error("Servlet注册反射方法异常！ " + url, e);
        }
    }

    protected void enableAjax() {

        getResponse().setCharacterEncoding("utf-8");
        getResponse().setContentType("application/json");
    }

    private GenericServlet(GenericServletBuilder builder) {

        setRequest(builder.request);
        setResponse(builder.response);
        setClazz(builder.clazz);

        String url_ = builder.url;
        setUrl( //
            null == url_ || url_.isEmpty()
                ? // 解析默认url
                getRequest().getPathInfo().substring(1, getRequest().getPathInfo().length())
                : // 传入自定义url
                url_
        );

        if(isAjax) enableAjax();

    }

    public static class GenericServletBuilder {

        private HttpServletRequest request;

        private HttpServletResponse response;

        private String url;

        private Boolean isRedirect = false;

        private Boolean isAjax = false;

        private Class<? extends GenericServlet> clazz;

        public GenericServletBuilder(HttpServletRequest request, HttpServletResponse response, Class<? extends GenericServlet> clazz) {

            this.setRequest(request).setResponse(response).setClazz(clazz);
        }

        public GenericServlet build() {

            return new GenericServlet(this);
        }

        public GenericServletBuilder setUrl(String url_) {
            url = url_;
            return this;
        }

        public GenericServletBuilder setRequest(HttpServletRequest request_) {
            request = request_;
            return this;
        }

        public GenericServletBuilder setResponse(HttpServletResponse response_) {
            response = response_;
            return this;
        }

        public GenericServletBuilder setRedirect(Boolean isRedirect_) {
            isRedirect = isRedirect_;
            return this;
        }

        public GenericServletBuilder setAjax(Boolean isAjax_) {
            isAjax = isAjax_;
            return this;
        }

        public GenericServletBuilder setClazz(Class<? extends GenericServlet> clazz_) {
            clazz = clazz_;
            return this;
        }

    }

    protected static HttpSession getSession() { //
        return session;
    }

    protected synchronized static void setSession(HttpSession session_) {//
        session = session_;
    }

    protected static User getSessionUser() { //
        return sessionUser;
    }

    protected synchronized static void setSessionUser(User sessionUser_) { //
        sessionUser = sessionUser_;
    }

    protected HttpServletRequest getRequest() {
        return request;
    }

    protected void setRequest(HttpServletRequest request) {
        this.request = request;
    }

    protected Class<? extends GenericServlet> getClazz() {
        return clazz;
    }

    protected void setClazz(Class<? extends GenericServlet> clazz) {
        this.clazz = clazz;
    }

    protected void setResponse(HttpServletResponse response) {
        this.response = response;
    }

    protected HttpServletResponse getResponse() {
        return response;
    }

    protected String getUrl() {
        return url;
    }

    protected void setUrl(String url) {
        this.url = url;
    }

    protected Boolean getRedirect() {
        return isRedirect;
    }

    protected void setRedirect(Boolean redirect) {
        isRedirect = redirect;
    }

    protected Boolean getAjax() {
        return isAjax;
    }

    protected void setAjax(Boolean ajax) {
        isAjax = ajax;
    }
}
